Inside Macintosh: Memory

Previous | Chapter Top | Chapter Contents | Next

Maintaining a Memory Reserve

A simple way to help ensure that your application always has enough memory available for essential operations is to maintain an emergency memory reserve. This memory reserve is a block of memory that your application uses only for essential operations and only when all other heap space has been allocated. This section illustrates one way to implement a memory reserve in your application.

To create and maintain an emergency memory reserve, you follow three distinct steps:

To refer to the emergency reserve, you can declare a global variable of type Handle .

VAR
    gEmergencyMemory:       Handle;     {handle to emergency memory reserve}

Listing 1-9 defines a function that you can call early in your application's execution (before entering your main event loop) to create an emergency memory reserve. This function also installs the application-defined grow-zone procedure. See "Defining a Grow-Zone Function" for a description of the grow-zone function.

Listing 9 Creating an emergency memory reserve

PROCEDURE InitializeEmergencyMemory;
BEGIN
    gEmergencyMemory := NewHandle(kEmergencyMemorySize);
    SetGrowZone(@MyGrowZone);
END;

The InitializeEmergencyMemory procedure defined in Listing 1-9 simply allocates a relocatable block of a predefined size. That block is the emergency memory reserve. A reasonable size for the memory reserve is whatever size you use for the memory cushion. Once again, 40 KB is a good size for many applications.

CONST
    kEmergencyMemorySize =          40 * 1024;      {size of memory reserve}

When using a memory reserve, you need to change the IsMemoryAvailable function defined earlier in Listing 1-5 . You need to make sure, when determining whether a nonessential memory allocation request should be honored, that the memory reserve has not been released. To check that the memory reserve is intact, use the function IsEmergencyMemory defined in Listing 1-10 .

Listing 10 Checking the emergency memory reserve

FUNCTION IsEmergencyMemory: Boolean;
BEGIN
    IsEmergencyMemory :=
        (gEmergencyMemory <> NIL) & (gEmergencyMemory^ <> NIL);
END;

Then, you can replace the function IsMemoryAvailable defined in Listing 1-5 ( Determining whether allocating memory would deplete the memory cushion ) by the version defined in Listing 1-11 .

Listing 11 Determining whether allocating memory would deplete the memory cushion

FUNCTION IsMemoryAvailable (memRequest: LongInt): Boolean;
VAR
    total:      LongInt;        {total free memory if heap purged}
    contig:     LongInt;        {largest contiguous block if heap purged}
BEGIN
    IF NOT IsEmergencyMemory THEN           {is emergency memory available?}
        IsMemoryAvailable := FALSE
    ELSE
    BEGIN
        PurgeSpace(total, contig);
        IsMemoryAvailable := ((memRequest + kMemCushion) < contig);
    END;
END;

As you can see, this is exactly like the earlier version except that it indicates that memory is not available if the memory reserve is not intact.

Once you have allocated the memory reserve early in your application's execution, it should be released only to honor essential memory requests when there is no other space available in your heap. You can install a simple grow-zone function that takes care of releasing the reserve at the proper moment. Each time through your main event loop, you can check whether the reserve is still intact; to do this, add these lines of code to your main event loop, before you make your event call:

IF NOT IsEmergencyMemory THEN
    RecoverEmergencyMemory;

The RecoverEmergencyMemory function, defined in Listing 1-12 , simply attempts to reallocate the memory reserve.

Listing 12 Reallocating the emergency memory reserve

PROCEDURE RecoverEmergencyMemory;
BEGIN
    ReallocateHandle(gEmergencyMemory, kEmergencyMemorySize);
END;

If you are unable to reallocate the memory reserve, you might want to notify the user that because memory is in short supply, steps should be taken to save any important data and to free some memory.


© 1997 Apple Computer, Inc.

Previous | Chapter Top | Chapter Contents | Next